Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.
In this article, we’ll look at how to create multilingual Vue apps with vue-i18n.
Custom Directive Localization
We can use the v-t
directive for getting translations.
For instance, we can write:
main.js
import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";
Vue.use(VueI18n);
Vue.config.productionTip = false;
const messages = {
en: {
hello: "hi"
},
fr: {
hello: "bonjour"
}
};
const i18n = new VueI18n({
messages,
locale: "fr"
});
new Vue({
i18n,
render: h => h(App)
}).$mount("#app");
App.vue
<template>
<div id="app">
<p v-t="'hello'"></p>
</div>
</template>
<script>
export default {
name: "App"
};
</script>
We just put the v-t
directive in our template and we get the translation.
So bonjour
is displayed on the screen.
We can also write:
main.js
import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";
Vue.use(VueI18n);
Vue.config.productionTip = false;
const messages = {
en: {
hello: "hi {name}"
},
fr: {
hello: "bonjour {name}"
}
};
const i18n = new VueI18n({
messages,
locale: "fr"
});
new Vue({
i18n,
render: h => h(App)
}).$mount("#app");
App.vue
<template>
<div id="app">
<p v-t="{ path: 'hello', args: { name: nickName } }"></p>
</div>
</template>
<script>
export default {
name: "App",
computed: {
nickName() {
return "foo";
}
}
};
</script>
to interpolate translation.
The path
has the path to the message, args
has dynamic arguments.
Now we get bonjour foo
displayed on the screen.
Use with Transitions
We can use the v-t
directive with transitions.
For instance, we can write:
main.js
import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";
Vue.use(VueI18n);
Vue.config.productionTip = false;
const messages = {
en: {
hello: "hi"
},
fr: {
hello: "bonjour"
}
};
const i18n = new VueI18n({
messages,
locale: "fr"
});
new Vue({
i18n,
render: h => h(App)
}).$mount("#app");
App.vue
<template>
<div id="app">
<button @click="toggle = !toggle">Toggle</button>
<transition name="fade">
<p v-t="'hello'" v-if="toggle"></p>
</transition>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
toggle: true
};
}
};
</script>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
Then we get a transition effect thanks to the transition
component.
$t vs v-t
$t
is more flexible in that it can be used in component code and template.
However, it’s run every time a re-render occurs, which means it’s slower.
v-t
has better performance than $t
because of caching.
It’s also can be used for pre-translation with vue-i18n-extensions
.
However, it isn’t as flexible as $t
and it’s complex.
Component Interpolation
To add translations with HTML, we may want to put them ibn between our tags:
main.js
import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";
Vue.use(VueI18n);
Vue.config.productionTip = false;
const messages = {
en: {
hello: "hi",
world: "world"
},
fr: {
hello: "bonjour",
world: "monde"
}
};
const i18n = new VueI18n({
messages,
locale: "fr"
});
new Vue({
i18n,
render: h => h(App)
}).$mount("#app");
App.vue
<template>
<div id="app">
<p>
{{ $t('hello') }}
<b>{{ $t('world') }}</b>
</p>
</div>
</template>
<script>
export default {
name: "App"
};
</script>
However, this is too inflexible.
We can use the i18n
component to avoid this.
For instance, we can write:
main.js
import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";
Vue.use(VueI18n);
Vue.config.productionTip = false;
const messages = {
en: {
hello: "hi {0}",
world: "world"
},
fr: {
hello: "bonjour {0}",
world: "monde"
}
};
const i18n = new VueI18n({
messages,
locale: "fr"
});
new Vue({
i18n,
render: h => h(App)
}).$mount("#app");
App.vue
<template>
<div id="app">
<i18n path="hello" tag="p" for="world">
<b>{{ $t('world') }}</b>
</i18n>
</div>
</template>
<script>
export default {
name: "App"
};
</script>
We have the {0}
placeholder to interpolate what we have inside i18n
into the tags.
Then we see the 2nd word in bold.
Conclusion
We can put HTML formatted text in the i18n
component.
Also, we can use the v-t
directive as an alternative to $t
.
It’s faster and works with transitions.